/*
	WindowTarget.cpp

	This window object is used to display / track an object in the game
	(c)2000 Palestar, Richard Lyle
*/

#define INTERFACE_DLL
#include "Debug/Assert.h"
#include "Render3d/NodeLight.h"
#include "Render3d/NodeSound.h"
#include "Interface/WindowTarget.h"
#include "Interface/GameDocument.h"
#include "Game/NounUnit.h"
#include "Game/NounCargo.h"
#include "Game/NounStructure.h"
#include "Game/NounDropTarget.h"
#include "Game/NounBeacon.h"

//----------------------------------------------------------------------------

IMPLEMENT_FACTORY( WindowTarget, NodeWindow );
REGISTER_FACTORY_KEY( WindowTarget, 4109377257530988770 );

WindowTarget::WindowTarget()
{}

//----------------------------------------------------------------------------

void WindowTarget::onRender( RenderContext & context, const RectInt & window )
{
	GameDocument * pDoc = (GameDocument *)document();
	if ( pDoc != NULL )
	{
		if ( pDoc->target() != NULL && pDoc->ship() != NULL )
		{
			Noun * pTarget = pDoc->target();
			if ( dynamic_cast<NounDropTarget *>( pTarget ) )
				pTarget = ((NounDropTarget *)pTarget)->planet();

			// get the hull of the object
			float scale = 2.0f / pTarget->hull().radius();

			Matrix33 targetFrame( pTarget->frame() );

			// calculate the view direction from the players ship
			Vector3 view;
			if ( dynamic_cast<NounGadget *>( pTarget ) 
				|| dynamic_cast<NounUnit *>( pTarget ) 
				|| dynamic_cast<NounStructure *>( pTarget ) 
				|| dynamic_cast<NounCargo *>( pTarget ) )
			{
				view = Vector3(cos(m_ActiveTime),-1,sin(m_ActiveTime) );
				targetFrame = Matrix33( true );
			}
			else if ( pDoc->ship() != pTarget )
				view = pTarget->worldPosition() - pDoc->ship()->worldPosition();
			else
				view = Vector3(1,-1,1);
			view.normalize();
			
			Matrix33 cameraFrame( view );
			cameraFrame = cameraFrame * targetFrame;
			Vector3 cameraPosition( view * 4.0f );

			RectInt previousWindow( context.window() );

			context.setPosition( cameraPosition );
			context.setFrame( cameraFrame );
			context.setWindow( window );
			context.setTime( pDoc->tick() * TICK_DURATION_S );
			context.flush();

			DisplayDevice * pDisplay = context.display();
			ASSERT( pDisplay );

			pDisplay->setAmbient( WHITE );
			pDisplay->clearLights();

			// disable lights
			NodeLight::s_bDisable = true;
			NodeSound::s_bDisable = true;

			// render the target object
			pTarget->render( context, cameraFrame * scale, Vector3( 0, 0, 4.0f ) );

			// enable lights
			NodeLight::s_bDisable = false;
			NodeSound::s_bDisable = false;

			context.setWindow( previousWindow );
			context.flush();

			// restore the ambient light
			pDisplay->setAmbient( UNIVERSE_AMBIENT );
		}
	}
}

//----------------------------------------------------------------------------
// EOF
